#! /usr/bin/env python
# -*- coding: utf-8 -*-
import time
import os
import re
import json
import random
import traceback

import requests
from requests.compat import cookielib

import FileHostProtoType

TURBOBIT_SERVER_STATUS = {'green':0,
                          'yellow':1,
                          'red':2}

DEFAULT_USER_AGENT = 'User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.106 Safari/535.2'
DEFAULT_REFERER = 'http://turbobit.net/'  
COOKIEJAR_CLASS = cookielib.MozillaCookieJar    

class tbitem(FileHostProtoType.HostItem):
    def __init__(self, name, type, code, link='', encrypt_name='', server_name=''):
        FileHostProtoType.HostItem.__init__(self, name, type, code, link, encrypt_name, server_name)
    
class turbobit(FileHostProtoType.FileHostProcess):     
    def __init__(self, user, pwd):
        FileHostProtoType.FileHostProcess.__init__(self)
        self.hostname = "TurboBit" 
        self._opener = None
        self._user = user
        self._pwd = pwd
        self.islogin = False
        self.isanoy = False
        self.logtype = 'poster'
        self._cookieCurl = '%s_%s.cookie' % (self._user, self.hostname)
        self._cookieCurl = os.path.join(os.path.dirname(__file__), self._cookieCurl)
        
        self.userid = ''
        self.apptype = ''
        self.recommend_servers = []
        self.deprecate_servers = []
        
        
        self._cj = COOKIEJAR_CLASS(self._cookieCurl)
        self.session = requests.session(cookies=self._cj)
        self.session.headers['User-Agent'] = DEFAULT_USER_AGENT
        self.session.headers['Referer'] = DEFAULT_REFERER
        if self.proxy:
            self.session.proxies = {'http', self.proxy}
        
        
    def login(self):
        '''
        login to TurboBit
        return opener object which includes cookies
        '''
        self.generateOpener()
        
        if not self.check_service_status():
            return False
            
        if self.restore_cookiejar():
            return True
        
        self.fherr.write('login to TurboBit %s/%s...' % (self._user,'*'*len(self._pwd)))
        
        #post login request
        loginData = {'user[submit]' : 'Login', 
                'user[login]' : self._user, 
                'user[pass]' : self._pwd,
                'user[memory]' : 'on'}
        
        loginresult = self.tb_request("http://turbobit.net/user/login", data=loginData)
        
        if "Limit of login attempts exeeded." in loginresult:
            self.fherr.write("Banned by Turbobit.")
            return False
            
        indexpage = self.tb_request("http://turbobit.net/")
            
        #you always see you username at the top of the page, if it logins successfully.
        if self._user.lower() not in indexpage.lower():
            self.fherr.write(loginresult)
            self.fherr.write("User %s Failed to Login TurboBit." % self._user)
            return False
        self.fherr.write("User %s logined." % self._user)
        self.islogin = True
        self._cj.save(ignore_discard=True)
        return True
    
    def check_service_status(self):
        indexpage = self.tb_request("http://turbobit.net/", cookies=dict(user_lang='en'))
        
        if 'temporarily unavailable' in indexpage.lower():
            self.fherr.write('[%s]Uploading is temporarily unavailable.' % time.ctime())
            return False
        return True

    def check_cookie(self):
        self.fherr.write('Checking Cookie...')
        response = self.tb_request("http://turbobit.net/")        
        if response and self._user in response:
            self.fherr.write("User %s Status : Logined." % self._user)
            self.islogin = True             
            return True
        self.fherr.write("[%s]User %s Status : not Logined." % (time.ctime(), self._user))
        return False  
    
    def restore_cookiejar(self):
        '''
        load cookie file, then access website to verify if cookie is avaiable
        '''
        if os.path.isfile(self._cookieCurl):
            self.fherr.write('Restore Local Cookie.')
            try:
                self._cj.load(ignore_discard=True)
            except:
                self.fherr.write('Failed to Restore Local CookieJar.')
            #access website to confirm cookie is avaiable
            return self.check_cookie()
        return False
        
    def upload_web(self, file, progressLog=None, other_args=None, send_range=None):
        return self.upload_web_local_register(file, progressLog, other_args, send_range)
        
    def upload_web_local_register(self, file, progressLog=None, other_args=None, send_range=None):
        lowest_load_server = self.get_lowest_load_server()
        urlsite = "http://s{}.turbobit.ru/uploadfile".format(lowest_load_server)
        
        if lowest_load_server == -1 or not self.userid:
            indexpage = self.tb_request("http://turbobit.net/")
            
            # urlsite = self.get_upload_key(indexpage, "urlSite", -1, 'urlSite=')
            # urlsite = urlsite[:urlsite.find('&')]
            userid = self.get_upload_key(indexpage, "userId", -1, 'userId=')
            userid = userid[:userid.find('&')]
            apptype = self.get_upload_key(indexpage, "apptype", -1, 'apptype=')
            apptype = apptype[:apptype.find('"')]
            self.userid = userid
            self.apptype = apptype
        
        if not self.userid:
            self.fherr.write(indexpage)
            self.fherr.write("Failed to get userid")
            return
        
        
        print lowest_load_server, self.userid, self.apptype, urlsite
        callback = None
        if progressLog is not None:
            callback = progressLog.write
        filesize = os.path.getsize(file)
        filename = self.rename_func(file)
        start_point = 0
        info = "Uploading...%s" % file
        if send_range is not None:
            #range is a 3-tuple, <start, end, number>
            filesize = send_range[1] - send_range[0] + 1
            filename += ".%03d" % send_range[2]
            start_point = send_range[0]
            info += " part%d" % send_range[2]
        
        self.fherr.write(info) 
        fileobj = open(file, 'rb')
        fileobj.seek(start_point)  
        data = {'Filedata' : fileobj,
                'Filename' : filename,
                'stype' : 'null',
                'apptype' : self.apptype,
                'user_id' : self.userid,
                'id' : 'null'}
        
        uploadurl = urlsite
        upload_response = self.post_request(uploadurl, data, retry=1,\
                                            cb=callback, \
                                            setfilename=filename,\
                                            setfilesize=filesize)
                                            
        if upload_response is None:
            self.deprecate_servers.append(lowest_load_server)
            return
            
        content = json.loads(upload_response)
        if "Everything is ok" in upload_response: 
            
            code = content["id"]
            basename = os.path.basename(file) 
            item = tbitem(basename, 'file', 
                          code, 
                          "http://turbobit.net/%s/%s.html" % (code, filename), 
                          filename)
            self.newupload.append(item)    
            print "add", lowest_load_server, "to recommend_servers."
            if not lowest_load_server in self.recommend_servers:
                self.recommend_servers.append(lowest_load_server)
            return item
        else:
            #it seems something wrong >__<
            self.fherr.write("upload url: {}\n".format(uploadurl)) 
            self.fherr.write("upload response: {}\n".format(upload_response)) 
            self.fherr.write("Message: %s" % content['message']) 
            self.fherr.write("Failed to get key after uploaded for %s" % file)
            return 
    
    def get_server_status(self):
        server_status = []
        server_info = self.tb_request("http://turbobit.net/upload/ftp")
        re_ftp = re.compile("<img src='\/fd1\/img\/icon\/ftp\/(?P<status>.*?)\.png'.*?ftp://s(?P<server_no>\d+)\.turbobit\.ru", re.I|re.S)
        result = re_ftp.finditer(server_info)
        for mi in result:
            status = mi.group('status')
            status = TURBOBIT_SERVER_STATUS[status]
            server_no = mi.group('server_no')
            if status == 2:
                #red!
                continue
            if server_no in self.deprecate_servers:
                print "tb give me a deprecate_server", server_no
                continue
            server_status.append((status, server_no))
        #server_status.sort()
        return server_status
    
    def get_lowest_load_server(self):
        print "check servers:", self.recommend_servers
        if self.recommend_servers:
            return self.recommend_servers[0]
        server_status = self.get_server_status()
        if not server_status:
            return -1
        rand_s = random.randint(0, len(server_status)-1)
        return server_status[rand_s][1]
            
    def tb_request(self, url, data=None, cookies={}):
        '''
        use requests to send request to turbobit.
        '''
        retry = 3
        while(retry  > 0):
            try:
                if data is None:
                    r = self.session.get(url, cookies=cookies)
                else:
                    r = self.session.post(url, data=data, cookies=cookies)
                return r.text
            except:
                traceback.print_exc()
                print 'Fail to Get url, retry...'
                print url
                return None
            retry -= 1
            